{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Part 2 - Grid as a Secure MLaaS"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p align=\"center\">\n",
    "<img height=\"800px\" width=\"800px\" src=\"./images/secure_mlaas.png\">\n",
    "</p>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As mentioned in the previous section, we can use the Grid platform to run **encrypted models** and **perform inferences using encrypted input data**.  \n",
    "\n",
    "&nbsp;Therefore, the Grid platform can work as an agnostic cloud service that can manage encrypted models stored and distributed over the cloud provider's infrastructure, protecting intellectual property and preserving user's privacy at the same time.  \n",
    "\n",
    "Authors:\n",
    " - Ionésio Junior - Github: [IonesioJunior](https://github.com/IonesioJunior)\n",
    "\n",
    "\n",
    "&nbsp; In this section, we'll learn **how to host and serve MPC models on the grid platform**.\n",
    "\n",
    "**NOTE:** At the time of running this notebook, we were running the grid components in background mode.  \n",
    "\n",
    "Components:\n",
    " - Grid Gateway(http://localhost:5000)\n",
    " - Grid Node Bob ( ws://localhost:3000 )\n",
    " - Grid Node Alice ( ws://localhost:3001 )\n",
    " - Grid Node Bill ( ws://localhost:3002 )\n",
    " - Grid Node James ( ws://localhost:3003 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Importing dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import syft as sy\n",
    "import torch as th\n",
    "import torch.nn.functional as F\n",
    "from syft.workers.node_client import NodeClient\n",
    "\n",
    "hook = sy.TorchHook(th)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  2.1 - Host a mpc model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.1.1 - Building our model\n",
    "To simplify our example, we'll use a toy model that has not been trained previously."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "sy.hook.local_worker.is_client_worker = False # We need to set up this flag to save plans states during model's build.\n",
    "\n",
    "# Your model needs to extends syft plans\n",
    "class Net(sy.Plan):\n",
    "    def __init__(self):\n",
    "        super(Net, self).__init__(id=\"convnet\") # ID used to identify this model \n",
    "        self.fc1 = th.tensor([2.0, 4.0])\n",
    "        self.bias = th.tensor([1000.0])\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.fc1.matmul(x) + self.bias\n",
    "\n",
    "# Create an instance of it.\n",
    "model = Net()\n",
    "\n",
    "# Build model's plan sending any valid input (input's shape needs to match with model's dimensions)\n",
    "model.build(th.tensor([1.0, 2]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.1.2 - Hosting at  Grid\n",
    "As a company, after creating a model, we want to publish it on the cloud provider's infrastructure in a secure way."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# We'll use the grid platform as a cloud service.\n",
    "cloud_grid_service = sy.PublicGridNetwork(hook, \"http://localhost:5000\")\n",
    "\n",
    "'''\n",
    "This method will split your model weights into pieces,\n",
    "distributing them through the grid network,\n",
    "and storing a pointer plan that manages all remote references.\n",
    "'''\n",
    "cloud_grid_service.serve_model(model,id=model.id,allow_remote_inference=True, mpc=True) # If mpc flag is False, It will host a unencrypted model."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's important to note that the **cloud_grid_service does not have access to the real model**. It has only mpc slices distributed over the platform.  \n",
    "\n",
    "**In a cyber-attack scenario, the malicious agent must invade all nodes involved in the mpc process to retrieve the original model.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 - Running encrypted inferences"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As a user, we want to run inferences on our private data without sending them to anyone.  \n",
    "\n",
    "PS: We will run it on this notebook, but in a real environment, this section needs to be implemented using syft.js library!  \n",
    "The user data should never be sent over the wire, so front-end will be the best place to do it **(the private data should be encrypted on the user's device)**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Inference's result:  tensor([1022.])\n"
     ]
    }
   ],
   "source": [
    "# Private user data that needs to be protected\n",
    "user_input_data = th.tensor([5.0, 3])\n",
    "\n",
    "'''\n",
    "This method will search the desired encrypted model,\n",
    "split your private data and send their slices\n",
    "to the same nodes that stores the mpc model weights,\n",
    "perform a distributed computing between mpc weights and mpc input data,\n",
    "receive the mpc results and aggregate it, returning the inference's result.\n",
    "'''\n",
    "result = cloud_grid_service.run_remote_inference(\"convnet\", user_input_data, mpc=True)# If mpc flag is False, It will send your real data to the platform.\n",
    "print(\"Inference's result: \", result) # ( [2.0, 4.0] * [5.0, 3.0] ) + [1000] = [1022]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Congratulations!!! - Time to Join the Community!\n",
    "\n",
    "Congratulations on completing this notebook tutorial! If you enjoyed this and would like to join the movement toward privacy preserving, decentralized ownership of AI and the AI supply chain (data), you can do so in the following ways!\n",
    "\n",
    "### Star PySyft on GitHub\n",
    "\n",
    "The easiest way to help our community is just by starring the GitHub repos! This helps raise awareness of the cool tools we're building.\n",
    "\n",
    "- [Star PySyft](https://github.com/OpenMined/PySyft)\n",
    "\n",
    "### Join our Slack!\n",
    "\n",
    "The best way to keep up to date on the latest advancements is to join our community! You can do so by filling out the form at [http://slack.openmined.org](http://slack.openmined.org)\n",
    "\n",
    "### Join a Code Project!\n",
    "\n",
    "The best way to contribute to our community is to become a code contributor! At any time you can go to PySyft GitHub Issues page and filter for \"Projects\". This will show you all the top level Tickets giving an overview of what projects you can join! If you don't want to join a project, but you would like to do a bit of coding, you can also look for more \"one off\" mini-projects by searching for GitHub issues marked \"good first issue\".\n",
    "\n",
    "- [PySyft Projects](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n",
    "- [Good First Issue Tickets](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n",
    "\n",
    "### Donate\n",
    "\n",
    "If you don't have time to contribute to our codebase, but would still like to lend support, you can also become a Backer on our Open Collective. All donations go toward our web hosting and other community expenses such as hackathons and meetups!\n",
    "\n",
    "[OpenMined's Open Collective Page](https://opencollective.com/openmined)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
